﻿using System;
using System.Collections.Concurrent;
using System.Threading;

namespace BuddHa.Common.Pool
{
    public abstract class ModelPool<T> : IModelPool<T> where T : IDisposable
    {
        private readonly IModelPoolOption _modelPoolOption;
        private readonly ConcurrentQueue<T> _corePool;

        private int _count;

        public ModelPool(IModelPoolOption modelPoolOption)
        {
            _modelPoolOption = modelPoolOption;
            _corePool = new ConcurrentQueue<T>();
        }


        public void Dispose()
        {
            _count = 0;
            while (_corePool.TryDequeue(out var model))
            {
                model.Dispose();
            }
        }

        public virtual T Rent()
        {
            if (_corePool.TryDequeue(out var model))
            {
                Interlocked.Decrement(ref _count);
                return model;
            }
            return default;
        }

        public virtual bool Return(T model)
        {
            if (Interlocked.Increment(ref _count) <= _modelPoolOption.MaxSize)
            {
                _corePool.Enqueue(model);
                return true;
            }
            Interlocked.Decrement(ref _count);
            return false;
        }
    }
}
